from twisted.python import log
import GameState

# command_name => func
command_table = {}

def command(name):
    """Decorator that adds the function to the command_table"""
    def _add_to_command_table(function):
        command_table[name] = function
        return function
    return _add_to_command_table

class CommandNotFound(Exception):
  "This exception is raised if no command is found"

def interpret(ch, line):
    """
    Accepts an input string like 'look monster'. The first word is the command word. If there is a registered command
    called look, the interpreter will call that command and send the rest of the words as arguments (in a tuple)
    """
    command, space, args = line.partition(' ')
    args = args.split()
    
    possible_commands = [c for c in command_table if c.startswith(command)]
    possible_commands.sort()
    log.msg("Possible Commands: %s" % ' '.join(possible_commands))
    if command and possible_commands:
        cmd = command_table[possible_commands[0]]
        cmd(ch,args)
    else:
        raise CommandNotFound

@command('help')
def help_command(ch,args):
    """
    Usage:
    help [topic or command]

    Displays help for a specific topic or command.
    Lists available commands and topics with no arguments.
    """
    if len(args):
        topic = args[0]
        try:
            help_msg = '\n'.join([line.strip() for line in command_table[topic].__doc__.strip().split('\n')])
            ch.to_self( "%s%s" %  ("${green,bold}", help_msg) )
        except Exception:
            ch.to_self( "%s is not a valid help topic." % topic )
    else:
        buf = "${blue,bold}Help Topics:${reset}\n"
        topics = command_table.keys()
        topics.sort()
        i = 1
        for t in topics:
            buf += "%-16s" % t
            if i % 5 == 0:
                buf += "\n"
            i += 1
        ch.to_self( buf )

@command('force')
def force_command( ch, args ):
    """
    Syntax:
    force <player> <commands>

    Sends commands to the interpreter as player.
    """
    try:
        vict = GameState.get_character_in_world(args[0])
    except Exception, e:
        print e
        ch.to_self("You must supply a victim.")
        return

    if vict is None:
        ch.to_self("Can't find %s." % args[0])
        return

    try:
        cmds = " ".join(args[1:])
    except:
        ch.to_self("Force %s to do what?" % vict.username)
        return

    print "%s is forcing %s to |%s|" % (ch.username,vict.username,cmds)
    self.to_self("${yellow,bold}[FORCED]", prompt=False, prepend_newline=True)
    vict.interpret(cmds)
